package com.whut.webSocket;

import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


/**
 * Type: WebSocketServer
 * Description: WebSocketServer,实现服务器客户端平等交流，
 * 		达到服务器可以主动向客户端发生消息
 * @author fuzhenjie
 * @date 2019 04 31
 */
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketServer {

    /**
     * 日志记录器
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);


    /**
     * 使用道格李的ConcurrentHashSet, 放的是WebSocketServer而不是session为了复用自己方法
     */
    private static transient volatile Set<WebSocketServer> webSocketSet = ConcurrentHashMap.newKeySet();


    /**
     * 这是我自己建立的映射
     */
    private static transient volatile Map<Integer,WebSocketServer> webSocketMap = new ConcurrentHashMap<Integer, WebSocketServer>();

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    private Integer userId;
    private boolean isReLogging  = false;
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(@PathParam("userId")Integer userId, Session session) {
        //reLogin(userId);
        this.session = session;
        //String[] userArray = userId.split(",");
        this.userId = userId;
        //加入set中
        webSocketSet.add(this);
        //加入map中
        webSocketMap.put(userId,this);
        LOGGER.info("setNUM:"+webSocketSet.size());
        LOGGER.info("mapNUM:"+webSocketMap.size());
        sendMessage("连接成功");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //从set中删除
        webSocketSet.remove(this);
        if (!this.isReLogging){
            //从map中删除
            webSocketMap.remove(this.userId);
        }

        LOGGER.info("setNUM:"+webSocketSet.size());
        LOGGER.info("mapNUM:"+webSocketMap.size());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        LOGGER.info("来自客户端(" + session.getId() + ")的消息:" + message);
        //sendMessage("Hello, nice to hear you! There are " + webSocketSet.size() + " users like you in total here!");
    }

    /**
     * Title: onError
     * Description: 发生错误时候回调函数
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        LOGGER.error("webSocket发生错误:" + error.getClass() + error.getMessage());
    }

    /**
     * Title: sendMessage
     * Description: 向客户端发送消息
     * @param message
     * @throws IOException
     */
    public boolean sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
            return true;
        } catch (IOException error) {
            LOGGER.error("webSocket-sendMessage发生错误:" + error.getClass() + error.getMessage());
            return false;
        }
    }


    /**
     * @author fuzhenjie
     * 向客户端发送JSON数据
     * @date 10:18 19.6.11
     * @param object
     * @return boolean
     **/
    public boolean sendJson(Object object){
        try{
            this.session.getBasicRemote().sendObject(object);
            return true;
        }catch (Exception error){
            LOGGER.error("webSocket-sendJSON发生错误:" + error.getClass() + error.getMessage());
            return false;
        }
    }

    /**
    * 登录验证
    * @author fuzhenjie
    * @date 19.7.31 14:25
    * @param userId 用户ID
    */
    public void reLogin(Integer userId){
        if(webSocketMap.containsKey(userId)){
            //作出原先id下线的操作
            WebSocketServer oldw = webSocketMap.get(userId);
            oldw.isReLogging = true;
            oldw.sendMessage("code777");
        }
    }


    /**
    * 群发信息
    * @author fuzhenjie
    * @date 19.7.31 14:26
    * @param message 消息内容
    */
    public static void sendInfo(String message) {
        LOGGER.info("webSocket-sendInfo群发消息：" + message);
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage(message);
        }
    }

    /**
     * getOnlineCount
     * 获取连接数
     * @return int
     */
    public static int getOnlineCount() {
        return webSocketSet.size();
    }
}